#ifndef _SCRIPTABLE_OBJECT_H
#define _SCRIPTABLE_OBJECT_H

#include "com_service_provider.h"
#import "progid:SharePoint.OpenDocuments.3"
//#include "OWSSUP.h"

using namespace OWSSUPP;

struct ScriptableObject
{
	NPObject NPObj;
	NPP instance;
	IOWSNewDocument* comObj;
	IID cachedVersion;
};

NPObject* CreateScriptableObject(NPP instance);
HRESULT CoLoadInstance(REFCLSID rclsid, IUnknown* pUnkOuter, REFIID riid, LPVOID FAR* ppv);

inline bool CheckVersion(IID cached, IID required)
{
	return cached == required || __uuidof(IOWSNewDocument3) == cached || __uuidof(IOWSNewDocument) == required;
}

template <typename T>
T* GetOWSObject(ScriptableObject* obj)
{
	IID guid = __uuidof(T);
	if(obj->comObj != 0 && CheckVersion(obj->cachedVersion, guid))
		return static_cast<T*>(obj->comObj);

	CLSID clsid;
	HRESULT hr = CLSIDFromProgID(L"SharePoint.OpenDocuments.3", &clsid);
	if (S_OK != hr)
	{
		guid = __uuidof(IOWSNewDocument2);
		hr = CLSIDFromProgID(L"SharePoint.OpenDocuments.2", &clsid);
	}

	bool officeXP = false;
	if (S_OK != hr)
	{
		officeXP = true;
		guid = __uuidof(IOWSNewDocument);
		hr = CLSIDFromProgID(L"SharePoint.OpenDocuments.1", &clsid);
	}

	if (S_OK != hr || !CheckVersion(guid, __uuidof(T)))
	{
		return NULL;
	}

	T* newDocument = NULL;
	hr = officeXP ? CoLoadInstance(clsid, NULL, guid, (LPVOID*)&newDocument) //hack for office 2002
		: CoCreateInstance(clsid, NULL, CLSCTX_ALL, guid, (LPVOID*)&newDocument);
	if(hr != S_OK)
	{
		return NULL;
	}

	IObjectWithSite* pObjectWS=NULL;
	hr = newDocument->QueryInterface(IID_IObjectWithSite,(LPVOID*)&pObjectWS);
	if(hr != S_OK)
	{
		return NULL;
	}

	ServiceStub* serviceStub = new ServiceStub(obj->instance);
	hr = pObjectWS->SetSite(static_cast<IDispatch*>(serviceStub));
	if(hr != S_OK)
	{
		newDocument->Release();
		newDocument = 0;
	}

	obj->comObj = newDocument;
	obj->cachedVersion = guid;

	return newDocument;
}

#endif
